package com.fanketly.musicdiary.ui.components

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowLeft
import androidx.compose.material.icons.filled.KeyboardArrowRight
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import com.fanketly.musicdiary.data.model.DiaryModel
import com.fanketly.musicdiary.data.model.newDiaryModel
import com.fanketly.musicdiary.data.moodMap
import com.fanketly.musicdiary.domain.DiaryViewModel
import com.fanketly.musicdiary.ui.theme.BlackBackgroundColor
import com.fanketly.musicdiary.ui.theme.BlackBottomBackground
import com.fanketly.musicdiary.ui.theme.SecondaryColor
import com.fanketly.musicdiary.ui.theme.TextWhite
import io.github.boguszpawlowski.composecalendar.StaticCalendar
import io.github.boguszpawlowski.composecalendar.day.DayState
import io.github.boguszpawlowski.composecalendar.header.MonthState
import io.github.boguszpawlowski.composecalendar.rememberCalendarState
import io.github.boguszpawlowski.composecalendar.selection.SelectionState
import java.time.DayOfWeek
import java.time.format.TextStyle
import java.util.*

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun DiaryCalendar(
//    diaryList: List<DiaryModel>,
    viewModel: DiaryViewModel = hiltViewModel()
) {

    Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        var monthList by remember { mutableStateOf<List<DiaryModel>?>(null) }
        Spacer(modifier = Modifier.fillMaxHeight(0.16f))
        StaticCalendar(
            calendarState = rememberCalendarState(),
            showAdjacentMonths = false,
            dayContent = {
                //Find data for the current date
                monthList?.let { month ->
                    //Shows dark red and mood (if any) if diary is saved on current date
                    DiaryCalendarDay(
                        it, month,
                        onClick = viewModel::showDiaryListDetail
                    )
                }
            },
            weekHeader = { DiaryWeekHeader(it, textColor = TextWhite) },
            monthHeader = {
                //Find data for the current month
                val currentMonth = it.currentMonth
                monthList =
                    viewModel.getDiaries().filter { a -> a.year == currentMonth.year && a.month == currentMonth.monthValue }
                DiaryMonthHeader(it, textColor = TextWhite)
            }, today = viewModel.date
        )
    }
}

@Composable
fun <T : SelectionState> DiaryCalendarDay(
    state: DayState<T>,
    monthList: List<DiaryModel>,
    selectionColor: Color = BlackBottomBackground,
    onClick: (DiaryModel) -> Unit = {},
) {
    val date = state.date
    val model =
        monthList.find { a -> a.month == date.monthValue && a.dayOfMonth == date.dayOfMonth }
            ?: newDiaryModel(date)

    val moodEnum = moodMap[model.mood]
    val textColor = if (model.id != 0L) {
        moodEnum?.color ?: SecondaryColor
    } else Color.White
    val painterId = moodEnum?.image ?: -1
    Surface(
        modifier = Modifier
            .padding(2.dp)
            .aspectRatio(1f)
            .clickableCustomIndication() {
                onClick(model)
            },
        color = if (state.isCurrentDay) selectionColor else BlackBackgroundColor,
        shape = if (state.isCurrentDay) RoundedCornerShape(16.dp) else RectangleShape,
    ) {
        if (painterId != -1) {
            Image(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(top = 11.dp),
                painter = painterResource(id = painterId),
                contentDescription = "mood"
            )
            Text(
                text = date.dayOfMonth.toString(),
                textAlign = TextAlign.Center,
                fontSize = 13.sp,
                color = textColor
            )
        } else {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                Text(
                    text = date.dayOfMonth.toString(),
                    textAlign = TextAlign.Center,
                    fontSize = 20.sp,
                    color = textColor
                )
            }
        }
    }

}

@Composable
fun DiaryWeekHeader(
    daysOfWeek: List<DayOfWeek>,
    modifier: Modifier = Modifier,
    textColor: Color
) {
    Row(modifier = modifier) {
        daysOfWeek.forEach { dayOfWeek ->
            Text(
                textAlign = TextAlign.Center,
                text = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
                modifier = modifier
                    .weight(1f)
                    .wrapContentHeight(),
                fontSize = 22.sp,
                color = textColor
            )
        }
    }
}

@Composable
fun DiaryMonthHeader(
    monthState: MonthState,
    modifier: Modifier = Modifier,
    textColor: Color = MaterialTheme.colors.onSurface
) {
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically
    ) {
        IconButton(
            modifier = Modifier.testTag("Decrement"),
            onClick = { monthState.currentMonth = monthState.currentMonth.minusMonths(1) }
        ) {
            Image(
                imageVector = Icons.Default.KeyboardArrowLeft,
                colorFilter = ColorFilter.tint(textColor),
                contentDescription = "Previous",
            )
        }
        Text(
            modifier = Modifier.testTag("MonthLabel"),
            text = monthState.currentMonth.month
                .getDisplayName(TextStyle.FULL, Locale.getDefault())
                .lowercase()
                .replaceFirstChar { it.titlecase() },
            style = MaterialTheme.typography.h4,
            fontSize = 26.sp,
            color = textColor
        )
        Spacer(modifier = Modifier.width(8.dp))
        Text(
            text = monthState.currentMonth.year.toString(),
            style = MaterialTheme.typography.h4,
            fontSize = 26.sp,
            color = textColor
        )
        IconButton(
            modifier = Modifier.testTag("Increment"),
            onClick = { monthState.currentMonth = monthState.currentMonth.plusMonths(1) }
        ) {
            Image(
                imageVector = Icons.Default.KeyboardArrowRight,
                colorFilter = ColorFilter.tint(textColor),
                contentDescription = "Next",
            )
        }
    }
}
